package com.szxx.suit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import com.szxx.domain.Card;
import com.szxx.domain.Cards;
import com.szxx.domain.DdzCard;
import com.szxx.util.PokerUtil;

/**
 * 斗地主分析器 <br>
 *
 * @author Ambrose
 */
public abstract class DdzSuitAnalyzer extends AbstractSuitAnalyzer<DdzAnalysisResult> {
	
	/** 关键数量 */
	private static int LIMIT_SIZE = 20;

	@Override
	protected DdzAnalysisResult getSuitResult() {
		DdzAnalysisResult result = new DdzAnalysisResult();
		result.setType(getSuitType());
		return result;
	}
	
	@Override
	protected final boolean checkRule(Cards cards, AbstractSuitTerm term) {
		// 排序，null，牌，癞子
		PokerUtil.sortCards_asc(cards);
		if (cards.getCardList().get(0) == null) { // 传进来的牌不应该有null值
			return false;
		} else {
			((DdzAnalysisResult)cards.getResult()).collectNumber(cards, term);
			if (((DdzAnalysisResult) cards.getResult()).getCardNum() > LIMIT_SIZE) { // 20张以上？？
				return false;
			} else {
				return doCheckRule(cards, term, (DdzAnalysisResult) cards.getResult());
			}
		}
	}

	/**
	 * 规则校验
	 * 
	 * @param cards
	 * @param term
	 * @param result
	 */
	protected abstract boolean doCheckRule(Cards cards, AbstractSuitTerm term, DdzAnalysisResult result);
	
	@Override
	protected final void analysize(Cards cards, AbstractSuitTerm term) {
		DdzAnalysisResult result = (DdzAnalysisResult) cards.getResult();
		if (result.getLaziCardNum() != 0) { // 有癞子，做癞子填充
			List<Card> laiziCardList = cards.subList(result.getCardNum() - result.getLaziCardNum(), result.getCardNum());
			for (Card card : laiziCardList) {
				DdzCard ddzCard = (DdzCard) card;
				if (ddzCard.isLazi() && ddzCard.getLaziNumber() == 0) { // 这里不应该有癞子没有赋值
					logger.info("some laiziCard's laziNumber is not valued !!!");
					analysizeLaizi(cards, term, true);
				}
			}
		}
		sort(cards, term);
		// 默认取第一张value 做weight评估
		result.setWeight(cards.get(0).getValue());
	}

	@Override
	protected void sort(Cards cards, AbstractSuitTerm term) {
		((DdzAnalysisResult)cards.getResult()).collectNumber(cards, term);
		// 利用SortCard来辅助排序
		List<SortCard> sortCardList = new ArrayList<SortCard>();
		for (Card card : cards) {
			sortCardList.add(new SortCard(card, (DdzAnalysisResult) cards.getResult()));
		}
		// 张数多的，花色点数小的在前面...
		Collections.sort(sortCardList);
		// 还原排序好了的排列
		cards.getCardList().clear();
		for (SortCard sortCard : sortCardList) {
			cards.addCard(sortCard.getCard());
		}
	}
	
	/**
	 * 填充癞子，仅当牌中含有癞子，且不全是癞子的时候会进入这里
	 * 
	 * @param cards
	 * @param term
	 * @param onlyMaxValue 仅赋值最大
	 */
	@Override
	protected List<Cards> analysizeLaizi(Cards cards, AbstractSuitTerm term, boolean onlyMaxValue) {
		if (((DdzAnalysisResult) cards.getResult()).isAllCardLazi()) { // 全是癞子保持原值 比如 3*3* 就是一对3
			List<Cards> cardsResult = new LinkedList<Cards>();
			for (Card card : cards) {
				((DdzCard) card).changeCard(card.getNumber());
			}
			Cards cardsCopy = cards.clone();
			analysize(cardsCopy, term);
			cardsResult.add(cardsCopy);
			return cardsResult;
		} else {
			return doAnalysizeLaizi(cards, term, onlyMaxValue);
		}
	}

	/**
	 * 牌组中含有癞子但不全是癞子的情况
	 * 
	 * @param handCards
	 * @param term
	 * @param onlyMaxValue
	 * @return
	 */
	protected List<Cards> doAnalysizeLaizi(Cards handCards, AbstractSuitTerm term, boolean onlyMaxValue) {
		return new LinkedList<Cards>();
	}
	
	/**
	 * 提牌算法，从手牌中分析出对应可能符合牌型的牌出来 <br>
	 * 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
	 * 
	 * @param handCards
	 * @param term
	 * @param onlyMaxValue
	 * @return
	 */
	@Override
	public List<Cards> listPossibleCards(Cards handCards, AbstractSuitTerm term) {
		List<Cards> result = new LinkedList<Cards>();
		if (handCards != null && handCards.size() != 0) {
			// 排序，null，牌，癞子
			PokerUtil.sortCards_asc(handCards);
			if (handCards.getCardList().get(0) != null) { // 传进来的牌不应该有null值
				DdzAnalysisResult analysisresult = getSuitResult();
				if (result != null) {
					handCards.setResult(analysisresult);
					analysisresult.collectNumber(handCards, term);
					if (containsPossibleCards(handCards, term)) {
						result.addAll(doListPossibleCards(handCards, term));
					}
				}
			}
		} 
		return result;
	}
	
	/**
	 * 提牌算法，大致确认下手牌中是否可以分析出对应可能符合牌型的牌出来 <br>
	 * 
	 * @param handCards
	 * @param term
	 * @return
	 */
	protected boolean containsPossibleCards(Cards handCards, AbstractSuitTerm term) {
		return false;
	}

	/**
	 * 提牌算法，从手牌中分析出对应可能符合牌型的牌出来 <br>
	 * 比如手牌 21QJ986554443 可以出的单牌就有 5 4 2 1 Q J 9 8 6 3 考虑拆牌
	 * 
	 * @param handCards
	 * @param term
	 * @param onlyMaxValue
	 * @return
	 */
	protected List<Cards> doListPossibleCards(Cards handCards, AbstractSuitTerm term) {
		return new LinkedList<Cards>();
	}	
}
